﻿using System;
using System.Collections.Generic;
using System.Linq;

namespace Array3DExtensions
{
    /// <summary>
    /// Represents the coordinates of a cell in a 3D array
    /// Stanislav Radkov®  2012 :D 
    /// </summary>
    public partial class Index3D
    {
        public Int32 W { get; set; }
        public Int32 H { get; set; }
        public Int32 D { get; set; }

        #region Constructors

        public Index3D(Int32 w, Int32 h, Int32 d)
        {
            this.W = w;
            this.H = h;
            this.D = d;
        }

        public Index3D() : this(0, 0, 0)
        {
        }

        public static Index3D operator +(Index3D a, Index3D b)
        {
            Index3D result = new Index3D();
            result.W = a.W + b.W;
            result.H = a.H + b.H;
            result.D = a.D + b.D;

            return result;
        }

        public static Index3D operator -(Index3D a, Index3D b)
        {
            Index3D result = new Index3D();
            result.W = a.W - b.W;
            result.H = a.H - b.H;
            result.D = a.D - b.D;

            return result;
        }

        #endregion

        #region Public Methods

        public static bool operator ==(Index3D a, Index3D b)
        {
            return a.Equals(b);
        }

        public static bool operator !=(Index3D a, Index3D b)
        {
            return !a.Equals(b);
        }

        public override bool Equals(object obj)
        {
            if (obj == null) 
                return false;

            if (this.GetType() != obj.GetType()) 
                return false;

            Index3D otherIndex = (Index3D)obj;

            bool isWidthEqual = this.W == otherIndex.W;
            bool isHeightEqual = this.H == otherIndex.H;
            bool isDeepEqual = this.D == otherIndex.D;

            return isWidthEqual && isHeightEqual && isDeepEqual;
        }

        public override string ToString()
        {
            return String.Format("W:{0} H:{1} D:{2}", this.W, this.H, this.D);
        }
        #endregion
    }

    /// <summary>
    /// Represents the 6 directions
    /// Stanislav Radkov®  2012 :D 
    /// </summary>
    public partial class Index3D
    {
        //We assume top-left is [0,0,0]
        public static readonly Index3D Left = new Index3D(-1, 0, 0);
        public static readonly Index3D Right = new Index3D(1, 0, 0);
        public static readonly Index3D Up = new Index3D(0, -1, 0);
        public static readonly Index3D Down = new Index3D(0, 1, 0);
        public static readonly Index3D In = new Index3D(0, 0, 1);
        public static readonly Index3D Out = new Index3D(0, 0, -1);

        public static readonly List<Index3D> StraightDirections = new List<Index3D>() { Up, Down, Left, Right, In, Out };
        public static readonly List<Index3D> StraightAndDiagonalDirections = new List<Index3D>()
        {
            Up, Down, Left, Right, In, Out,
            Up + In + Left, Up + In + Right, Up + Out + Right, Up + Out + Left,
            Down + In + Left, Down + In + Right, Down + Out + Right, Down + Out + Left,
            Up + In, Up + Out, Down + In, Down + Out,
            Up + Left, Up + Right, Down + Left, Down + Right,
            In + Left, In + Right, Out + Left, Out + Right,
        };
    }
}
